using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
using System.Data.Odbc;
using System.Data;
using System.Diagnostics;

namespace Pix2Gallery2
{
    class ElementsInterface
    {
        // A bunch of constants for the properties of tags in Elements. I dont actually use all of these, but
        // am populating it for future possible use.
        const ulong HiddenFolderAtt = 4194306;
        const ulong PersonFolderAtt = 65539;
        const ulong PlaceFolderAtt = 131075;
        const ulong EventFolderAtt = 196611;
        const ulong OtherFolderAtt = 262147;
        const ulong CollFolderAtt = 524307;
        const ulong CollTopLevelFolderAtt = 524310;
        const ulong CollFolderGroupAtt = 524311;
        const ulong StarFolderAtt = 458755;
        const ulong MediaLibraryAtt = 524338;
        ulong CollTopLevelFolderID = 0;
        ulong HidenFolderID = 0;
        ulong FiveStarsFolderID = 0;
        ulong FourStarsFolderID = 0;
        ulong ThreeStarsFolderID = 0;
        ulong TwoStarsFolderID = 0;
        ulong OneStarsFolderID = 0;
        static private OleDbConnection PSEConnection = new OleDbConnection();
        private string DBPath;
        private ListView GalleryPhotoList = new ListView();
        private NameValueCollection AlbumList;
        private NameValueCollection AlbumImageList = new NameValueCollection();
        private uint[] CollectionFolderIDArray;
        private int CollectionsAddedToFolderIDArray;
        private int CollectionFolderIDArrayLength;
        private string CollectionFolderIDString;
        private Gallery2Interface G2int; //Global - got sick of passing it back and forth


        public void ConnectToPSEDB(string DBPath, Gallery2Interface NewG2int)
        {
            this.DBPath = DBPath;
            PSEConnection.ConnectionString =
                @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + DBPath;
            PSEConnection.Open();
            G2int = NewG2int;
        }
        public void DisconnectFromPSEDB()
        {
            if (AlbumImageList != null)
                AlbumImageList.Clear();
            this.DBPath = "";
            PSEConnection.Close();
            PSEConnection.Dispose();
        }
        public void PopulateCollectionTree(System.Windows.Forms.TreeView TreeViewColl)
        {

            CollectionFolderIDString = "";
            CollectionsAddedToFolderIDArray = 0;

            //This will populate the treeview with the collections

            //Firstly lets read the whole FolderTable into a DataTable
            OleDbDataAdapter da_Contacts;
            da_Contacts =
                new OleDbDataAdapter("Select * From FolderTable", PSEConnection);
            DataTable dt_Contacts = new DataTable();
            da_Contacts.Fill(dt_Contacts);

            //Check to make sure the table has something
            if (dt_Contacts.Rows.Count == 0)
            {
                return;
            }
            GetCollTopLevelFolderID();
            GetCollectionFolderIDArrayLength();
            OleDbDataAdapter da_TopLevelColl =
                new OleDbDataAdapter("Select * From FolderTable WHERE fFolderID = " + CollTopLevelFolderID.ToString(), PSEConnection);
            DataTable dt_TopLevelColl = new DataTable();
            da_TopLevelColl.Fill(dt_TopLevelColl);
            //There should only be one record here - the Top Level Collection record.
            ProcessSiblingCollectionTopLevel(Convert.ToUInt64(dt_TopLevelColl.Rows[0]["fFirstChildFolderId"].ToString()), TreeViewColl);

            for (int i = 0; i < CollectionFolderIDArray.Length; i++)
            {
                Debug.WriteLine(CollectionFolderIDArray[i]);
            }
            //Right about now, the CollectionFolderIDArray has all of the collection folderID's in it. Now to 
            //write something to cycle through them, get the photos that belong to each one, put them in AlbumImageList,
            //so they can be used for later.
            this.PopulateAlbumImageList(CollectionFolderIDArray);
        }
        private void GetCollTopLevelFolderID()
        {
            //This will find the ID ofthe top level folder ID.
            OleDbDataAdapter da_TopLevelColl;
            da_TopLevelColl =
                new OleDbDataAdapter("Select * From FolderTable WHERE fFolderAttributes = " + CollTopLevelFolderAtt.ToString(), PSEConnection);
            DataTable dt_TopLevelColl = new DataTable();
            da_TopLevelColl.Fill(dt_TopLevelColl);
            CollTopLevelFolderID = Convert.ToUInt64(dt_TopLevelColl.Rows[0]["fFolderID"].ToString());
            //MessageBox.Show(test.ToString());
            OleDbDataAdapter da_HiddenColl;
            da_HiddenColl =
                new OleDbDataAdapter("Select * From FolderTable WHERE fFolderAttributes = " + HiddenFolderAtt.ToString(), PSEConnection);
            DataTable dt_HiddenColl = new DataTable();
            da_HiddenColl.Fill(dt_HiddenColl);
            HidenFolderID = Convert.ToUInt64(dt_HiddenColl.Rows[0]["fFolderID"].ToString());

            // Now get the Star Folder ID's
            OleDbDataAdapter da_StarColl;
            da_StarColl =
                new OleDbDataAdapter("Select * From FolderTable WHERE fFolderAttributes = " + StarFolderAtt.ToString(), PSEConnection);
            DataTable dt_StarColl = new DataTable();
            da_StarColl.Fill(dt_StarColl);
            int FolderCount = dt_StarColl.Rows.Count;
            if (FolderCount != 0)
            {
                // I am making a big big assumption here that there will always either be 0 or 5 stars.
                FiveStarsFolderID = Convert.ToUInt64(dt_StarColl.Rows[0]["fFolderID"].ToString());
                FourStarsFolderID = Convert.ToUInt64(dt_StarColl.Rows[1]["fFolderID"].ToString());
                ThreeStarsFolderID = Convert.ToUInt64(dt_StarColl.Rows[2]["fFolderID"].ToString());
                TwoStarsFolderID = Convert.ToUInt64(dt_StarColl.Rows[3]["fFolderID"].ToString());
                OneStarsFolderID = Convert.ToUInt64(dt_StarColl.Rows[4]["fFolderID"].ToString());

            }
        }
        private void GetCollectionFolderIDArrayLength()
        {
            //This will get the count of collection folders (both folders and containers)
            OleDbDataAdapter da_Collections;
            da_Collections =
                new OleDbDataAdapter("Select * From FolderTable WHERE (fFolderAttributes = " + CollFolderAtt.ToString() +
                ") OR (fFolderAttributes = " + CollFolderGroupAtt.ToString() +
                ") OR (fFolderAttributes = " + CollTopLevelFolderAtt.ToString() +
                ") OR (fFolderAttributes = " + MediaLibraryAtt.ToString() + ")", PSEConnection);
            DataTable dt_Collections = new DataTable();
            da_Collections.Fill(dt_Collections);
            CollectionFolderIDArrayLength = dt_Collections.Rows.Count;
        }
        private void ProcessSiblingCollectionTopLevel(UInt64 SiblingID, TreeView TreeViewColl_Local)
        {
            //Should process the sibling collections
            OleDbDataAdapter da_FT_Local =
                new OleDbDataAdapter("Select * From FolderTable WHERE fFolderID = " + SiblingID.ToString(), PSEConnection);
            DataTable dt_FT_Local = new DataTable();
            da_FT_Local.Fill(dt_FT_Local);
            TreeNode tn_Coll_Local;
            tn_Coll_Local = TreeViewColl_Local.Nodes.Add(dt_FT_Local.Rows[0]["fFolderName"].ToString());
            //Using the Name property of the nodes to store the PSE Folder Id
            tn_Coll_Local.Name = SiblingID.ToString();
            if (CollectionFolderIDString == "")
                CollectionFolderIDString = SiblingID.ToString();
            else
                CollectionFolderIDString = CollectionFolderIDString + " , " + SiblingID.ToString();
            //CollectionFolderIDArray[CollectionFolderIDArray.Length] = Convert.ToUInt32(SiblingID);
            if (dt_FT_Local.Rows[0]["fFirstChildFolderId"].ToString() != "0")
            {
                //ProcessChildCollection(Convert.ToUInt64(dt_FT_Local.Rows[0]["fFirstChildFolderId"].ToString()), tn_Coll_Local);
                ProcessCollection(Convert.ToUInt64(dt_FT_Local.Rows[0]["fFirstChildFolderId"].ToString()), tn_Coll_Local, true);
            }
            if (dt_FT_Local.Rows[0]["fNextFolderId"].ToString() != "0")
            {
                ProcessSiblingCollectionTopLevel(Convert.ToUInt64(dt_FT_Local.Rows[0]["fNextFolderId"].ToString()), TreeViewColl_Local);
            }
            PopulateFolderIDArray(Convert.ToUInt32(SiblingID));

        }
        private void ProcessCollection(UInt64 ChildID, TreeNode tnCollParent, bool IsChild)
        {
            //Will process the Collections of PSE - Both Children and Siblings
            //Connect to database using new SQL statement
            OleDbDataAdapter da_FT_Local =
                new OleDbDataAdapter("Select * From FolderTable WHERE fFolderID = " + ChildID.ToString(), PSEConnection);
            DataTable dt_FT_Local = new DataTable();
            da_FT_Local.Fill(dt_FT_Local);
            TreeNode tnCollChild;
            //Insert new node under the parent.
            tnCollChild = tnCollParent.Nodes.Add(dt_FT_Local.Rows[0]["fFolderName"].ToString());
            //Using the Name property of the nodes to store the PSE Folder Id
            tnCollChild.Name = ChildID.ToString();
            //CollectionFolderIDArray[CollectionFolderIDArray.Length] = Convert.ToUInt32(ChildID);
            CollectionFolderIDString = CollectionFolderIDString + " , " + ChildID.ToString();
            //tnCollChild.
            //Add PSECOllection for reference
            //Add Children nodes if needed.
            if (dt_FT_Local.Rows[0]["fFirstChildFolderId"].ToString() != "0")
            {
                ProcessCollection(Convert.ToUInt64(dt_FT_Local.Rows[0]["fFirstChildFolderId"].ToString()), tnCollChild, true);
            }
            //Add Sibling nodes if needed
            if (dt_FT_Local.Rows[0]["fNextFolderId"].ToString() != "0")
            {
                ProcessCollection(Convert.ToUInt64(dt_FT_Local.Rows[0]["fNextFolderId"].ToString()), tnCollParent, false);
            }
            PopulateFolderIDArray(Convert.ToUInt32(ChildID));
        }
        private void PopulateFolderIDArray(uint FolderID)
        {
            if (CollectionsAddedToFolderIDArray == 0)
            {
                //If CollectionsAddedToFolderIDArray is 0, then this is the first to be added to the array
                //Initialise the array
                CollectionFolderIDArray = new uint[CollectionFolderIDArrayLength];
            }
            CollectionFolderIDArray[CollectionsAddedToFolderIDArray] = FolderID;
            CollectionsAddedToFolderIDArray++;
        }

        public string ReturnFullTreeIndex(TreeNode tnPar)
        {
            //Will return the node index back to the parent, in the format 1.2.1.2.5, where
            //The first (left most) is the parent index, and the last (right most) is the child index.
            //I need to do this, as I cant count on the text of the nodes being unique.
            //After writing this, I realised I didnt need it - but I'm going to leave it here. It might come in handy later.
            string ReturnString;
            ReturnString = tnPar.Index.ToString();
            ReturnString = GetParentTreeIndex(tnPar, ReturnString);
            return ReturnString;

        }
        private string GetParentTreeIndex(TreeNode tnChild, string ReturnString)
        {
            //This function is to be used by ReturnFullTreeIndex(). It assumes that the string passed to it
            //is already populated with the index of the TreeNode passsed to it - and it is to find the parent, and
            //add the index of the parent to ReturnString. If successful, then repeat, else return back to the calling function.
            //After writing this, I realised I didnt need it - but I'm going to leave it here. It might come in handy later.
            if (tnChild.Level == 0)
            {
                return (ReturnString);
            }
            TreeNode tnParent;
            tnParent = tnChild.Parent;
            ReturnString = tnParent.Index.ToString() + "." + ReturnString;
            ReturnString = GetParentTreeIndex(tnParent, ReturnString);
            return ReturnString;
        }

        public void PopulatePhotoList(ListView lvPhoto, uint[] FolderIdArray)
        {
            //This should populate the List View

            lvPhoto.Items.Clear();

            ListViewItem objListItem;
            OdbcCommand PSECommand = new OdbcCommand();
            PSECommand.CommandText = "SELECT fImageId, fMediaFullPath, fImageOriginalFileName, fFolderInfoArray from ImageTable";
            PSECommand.CommandText = "SELECT ImageTable.fImageId, ImageTable.fMediaFullPath, " +
                "MediaShortCaptionTable.fMediaShortCaption, ImageTable.fFolderInfoArray, " +
                "ImageLongCaptionTable.fImageLongCaption, ImageTable.fImageTime, ImageTable.fImageOriginalFileName " +
                "FROM (ImageTable LEFT JOIN MediaShortCaptionTable ON " +
                "ImageTable.fMediaShortCaptionIdFromMedia = MediaShortCaptionTable.fMediaShortCaptionId) LEFT JOIN " +
                "ImageLongCaptionTable ON ImageTable.fImageLongCaptionIdFromImage = ImageLongCaptionTable.fImageLongCaptionId";
            OdbcConnection PSEConnection = new OdbcConnection();
            //PSEConnection.ConnectionString = @"Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Users\shanon\Pictures\Adobe Photoshop Album\Shanons.psa";
            //LocConn.Driver = @"Provider=Microsoft.Jet.OLEDB.4.0";
            //LocConn.ConnectionString = @"C:\Users\shanon\Pictures\Adobe Photoshop Album\Shanons.psa";
            PSEConnection.ConnectionString = @"Driver={Microsoft Access Driver (*.mdb)};DBQ=" + this.DBPath;

            PSEConnection.Open();
            PSECommand.Connection = PSEConnection;
            PSECommand.CommandType = CommandType.Text;
            OdbcDataReader myReader = PSECommand.ExecuteReader(CommandBehavior.CloseConnection);
            byte[] FolderInfoArray_Bytes;
            uint[] FolderInfoArray_Uints;
            FolderInfoArray_Bytes = new byte[400];
            FolderInfoArray_Uints = new uint[100];

            while (myReader.Read())
            {
                //This is where things get tricky. The following bits of code will:
                //a) Grab the fFolderInfoArray field (a binary field) and put it into FolderInfoArray_Bytes,
                //   which is a 400 member array of Bytes
                //b) Convert these 400 bytes into 100 uints, and populate the FolderInfoArray_Uints (a 100
                //   member array of uints).

                //Firstly we clear the two arrays.
                Array.Clear(FolderInfoArray_Bytes, 0, FolderInfoArray_Bytes.Length);
                Array.Clear(FolderInfoArray_Uints, 0, FolderInfoArray_Uints.Length);

                //Populate the FolderInfoArray_Bytes array
                myReader.GetBytes(3, 0, FolderInfoArray_Bytes, 0, FolderInfoArray_Bytes.Length);
                //Populatethe FolderInfoArray_Uints array
                this.ConvertByteArrayToUintArray(FolderInfoArray_Bytes, FolderInfoArray_Uints);

                //Now we should have the FolderInfoArray_Uints array full of the folders linked to this record.
                //We need to compare this to the values in FolderIdArray, if we get any matches, then we
                //insert this record.
                if (this.MatchUintArrays(FolderIdArray, FolderInfoArray_Uints))
                {
                    objListItem = lvPhoto.Items.Add(myReader[0].ToString()); //fImageId - Integer ID of image
                    //TempString = TempString.Remove(TempString.Length - 1);
                    //We have to remove the last character from all of these, as they are currently garbage.
                    objListItem.SubItems.Add(RemoveLastCharacter(myReader[6].ToString())); //adjust //fImageOriginalFileName - Just the file name
                    objListItem.SubItems.Add(RemoveLastCharacter(myReader[1].ToString())); //fMediaFullPath - Full path and filename of the photo
                    objListItem.SubItems.Add(RemoveLastCharacter(myReader[2].ToString())); //fMediaShortCaption - Short caption of file.
                    objListItem.ImageKey = RemoveLastCharacter(myReader[1].ToString()); //fMediaFullPath - Full path and filename of the photo
                    objListItem.Checked = true;
                }
            }
        }
        public void PopulatePhotoListFromAlbumImageList(ListView lvPhoto, uint[] FolderIdArray)
        {
            //This should populate the List View from the information in AlbumImageList
            // folderid.xxx.image.yyy.imageid - imageID
            // folderid.xxx.image.yyy.fullpath - Full path /file name of image
            // folderid.xxx.image.yyy.filename - Name of file
            // folderid.xxx.image.yyy.shortcaption - Short Caption
            // folderid.xxx.image.yyy.longcaption - Long caption
            // folderid.xxx.image.yyy.stars - Stars. 0,1,2,3,4,5
            // folderid.xxx.image.yyy.exists - Image exists in PSE & Gallery.
            // folderid.xxx.imagecount - image count for this folder
            // folderid.xxx.imageexistcount - images that exists in gallery count


            lvPhoto.Items.Clear();
            int ImageCount;
            string ImageInfoReq = "folderid." + FolderIdArray[0].ToString() + ".image.";
            string ImageCountReq = "folderid." + FolderIdArray[0].ToString() + ".imagecount";
            if (AlbumImageList[ImageCountReq] != "")
                ImageCount = Convert.ToInt32(AlbumImageList[ImageCountReq]);
            else
                ImageCount = 0;

            ListViewItem objListItem;
            for (int i = 1; i <= ImageCount; i++)
            {
                string ImageIDReq = ImageInfoReq + i.ToString() + ".imageid";
                string ImageFullPathReq = ImageInfoReq + i.ToString() + ".fullpath";
                string ImageFileNameReq = ImageInfoReq + i.ToString() + ".filename";
                string ImageShortCapReq = ImageInfoReq + i.ToString() + ".shortcaption";
                string ImageLongCapReq = ImageInfoReq + i.ToString() + ".longcaption";
                string ImageStarsReq = ImageInfoReq + i.ToString() + ".stars";
                string ImageExistsReq = ImageInfoReq + i.ToString() + ".exists";
                objListItem = lvPhoto.Items.Add(AlbumImageList[ImageIDReq]); //fImageId - Integer ID of image
                //TempString = TempString.Remove(TempString.Length - 1);
                //We have to remove the last character from all of these, as they are currently garbage.
                objListItem.SubItems.Add(AlbumImageList[ImageFileNameReq]); //adjust //fImageOriginalFileName - Just the file name
                objListItem.SubItems.Add(AlbumImageList[ImageFullPathReq]); //fMediaFullPath - Full path and filename of the photo
                objListItem.SubItems.Add(AlbumImageList[ImageShortCapReq]); //fMediaShortCaption - Short caption of file.
                objListItem.SubItems.Add(AlbumImageList[ImageStarsReq]);    //Should be the starts as an integer.
                //objListItem.ImageKey = AlbumImageList[ImageFullPathReq]; //fMediaFullPath - Full path and filename of the photo
                string ImageExistsString = AlbumImageList[ImageExistsReq];
                int ImageIndex;
                switch (ImageExistsString)
                {
                    case "True":
                        ImageIndex = 3; //Green
                        break;
                    case "False":
                        ImageIndex = 1; //Red
                        break;
                    default:
                        ImageIndex = 0; //White
                        break;
                }


                objListItem.ImageIndex = ImageIndex;
                objListItem.Checked = true;
            }



        }

        public void PopulateAlbumImageList(uint[] FolderIdArray)
        {
            //This should populate the AlbumImageList variable, for all the Folders provided in
            // FolderIdArray

            int RowPos = 0;

            OdbcCommand PSECommand = new OdbcCommand();

            string ImageTableSQLString = "SELECT ImageTable.fImageId, ImageTable.fMediaFullPath, " +
                "MediaShortCaptionTable.fMediaShortCaption, ImageTable.fFolderInfoArray, " +
                "ImageLongCaptionTable.fImageLongCaption, ImageTable.fImageTime, ImageTable.fImageOriginalFileName " +
                "FROM (ImageTable LEFT JOIN MediaShortCaptionTable ON " +
                "ImageTable.fMediaShortCaptionIdFromMedia = MediaShortCaptionTable.fMediaShortCaptionId) LEFT JOIN " +
                "ImageLongCaptionTable ON ImageTable.fImageLongCaptionIdFromImage = ImageLongCaptionTable.fImageLongCaptionId";
            PSECommand.CommandText = ImageTableSQLString;
            OdbcConnection PSEConnection = new OdbcConnection();
            PSEConnection.ConnectionString = @"Driver={Microsoft Access Driver (*.mdb)};DBQ=" + this.DBPath;

            PSEConnection.Open();
            PSECommand.Connection = PSEConnection;
            PSECommand.CommandType = CommandType.Text;
            //Count how many images there are. I really should do this in a more efficient way some time.
            OdbcDataReader ImageCounterReader = PSECommand.ExecuteReader(CommandBehavior.CloseConnection);
            int TotalImageCount = 0;
            while (ImageCounterReader.Read())
            {
                TotalImageCount++;
            }
            ImageCounterReader.Dispose();

            PSEConnection.Open();
            OdbcDataReader myReader = PSECommand.ExecuteReader(CommandBehavior.CloseConnection);
            byte[] FolderInfoArray_Bytes;
            uint[] FolderInfoArray_Uints;
            uint[,] AllFolderInfoArray_Uints;
            FolderInfoArray_Bytes = new byte[400];
            FolderInfoArray_Uints = new uint[100];
            AllFolderInfoArray_Uints = new uint[TotalImageCount, 100];
            while (myReader.Read())
            {
                //This is where things get tricky. The following bits of code will:
                //a) Grab the fFolderInfoArray field (a binary field) and put it into FolderInfoArray_Bytes,
                //   which is a 400 member array of Bytes
                //b) Convert these 400 bytes into 100 uints, and populate the FolderInfoArray_Uints (a 100
                //   member array of uints).
                //c) Put this into the AllFolderInfoArray_Uints

                //Firstly we clear the two arrays.
                Array.Clear(FolderInfoArray_Bytes, 0, FolderInfoArray_Bytes.Length);
                Array.Clear(FolderInfoArray_Uints, 0, FolderInfoArray_Uints.Length);

                //Populate the FolderInfoArray_Bytes array
                myReader.GetBytes(3, 0, FolderInfoArray_Bytes, 0, FolderInfoArray_Bytes.Length);
                //Populatethe FolderInfoArray_Uints array
                this.ConvertByteArrayToUintArray(FolderInfoArray_Bytes, FolderInfoArray_Uints);
                //Populate the AllFolderInfoArray_Uints array
                for (int i = 0; i < FolderInfoArray_Uints.Length; i++)
                {
                    AllFolderInfoArray_Uints[RowPos, i] = FolderInfoArray_Uints[i];
                }
                RowPos++;
            }
            // At this point the AllFolderInfoArray_Uints array should be full of the folders linked to each image
            // record (ImageTable). Now we need to:
            // 1) cycle through each FolderIdArray member
            // 2) Delete any existing entries in the AlbumImageList variable
            // 3) find the images that belong to this folder
            // 4) put them in the AlbumImageList variable.

            for (int i = 0; i < FolderIdArray.Length; i++)
            {
                //Cycling through each FolderIdArray member
                InsertAlbumImages(FolderIdArray[i], ImageTableSQLString, AllFolderInfoArray_Uints);
            }
        }
        private int ClearExistingAlbumImages(uint FolderIdToClear)
        {
            // This function will:
            // 1) remove all of the values in AlbumImageList relating to the folder FolderIdToClear
            // 2) update the count for total number of AlbumImages
            // 3) Return the number of values removed (It might be useful later)
            // The rules for what means what should be laid out in InsertAlbumImages
            return (0);
        }
        private int InsertAlbumImages(uint FolderIdToInsert, string ImageTableSQLString, uint[,] AllFolderInfoArray_Uints)
        {
            // This function will:
            // 1) Add all of the images relating to folder FolderIdToInsert to AlbumImageList
            // 2) update the count fortotal number of AlbumImages
            // 3) Return the number of values inserted (It might be useful later)
            // The format of the data is as follows:
            // (xxx is the FolderID, yyy is the sequential number of the image (for this folder)
            // folderid.xxx.image.yyy.imageid - imageID
            // folderid.xxx.image.yyy.fullpath - Full path /file name of image
            // folderid.xxx.image.yyy.filename - Name of file
            // folderid.xxx.image.yyy.shortcaption - Short Caption
            // folderid.xxx.image.yyy.longcaption - Long caption
            // folderid.xxx.image.yyy.stars - Stars. 0,1,2,3,4,5
            // folderid.xxx.image.yyy.exists - image exists in gallery
            // folderid.xxx.imagecount - image count for this folder
            // folderid.xxx.imageexistcount - images that exists in gallery count
            // folderid.xxx.allpseimagesexist - All images from this PSE collection exist in the gallery album

            //Firstly, delete existing images for this folder.
            string ImageInfoReq = "folderid." + FolderIdToInsert.ToString() + ".image.";
            string ImageCountReq = "folderid." + FolderIdToInsert.ToString() + ".imagecount";
            string ImageExistsCountReq = "folderid." + FolderIdToInsert.ToString() + ".imageexistcount";
            string AllPSEImagesExistReq = "folderid." + FolderIdToInsert.ToString() + ".allpseimagesexist";
            if (AlbumImageList[ImageCountReq] != "")
            {
                int CurrentImageCount = Convert.ToInt32(AlbumImageList[ImageCountReq]);
                for (int i = 1; i <= CurrentImageCount; i++)
                {
                    string ImageIDReq = ImageInfoReq + i.ToString() + ".imageid";
                    string ImageFullPathReq = ImageInfoReq + i.ToString() + ".fullpath";
                    string ImageFileNameReq = ImageInfoReq + i.ToString() + ".filename";
                    string ImageShortCapReq = ImageInfoReq + i.ToString() + ".shortcaption";
                    string ImageLongCapReq = ImageInfoReq + i.ToString() + ".longcaption";
                    string ImageExistsReq = ImageCountReq + i.ToString() + ".exists";
                    string ImageStarsReq = ImageInfoReq + i.ToString() + ".stars";
                    AlbumImageList.Remove(ImageIDReq);
                    AlbumImageList.Remove(ImageFullPathReq);
                    AlbumImageList.Remove(ImageFileNameReq);
                    AlbumImageList.Remove(ImageShortCapReq);
                    AlbumImageList.Remove(ImageLongCapReq);
                    AlbumImageList.Remove(ImageStarsReq);
                }
                AlbumImageList.Remove(ImageCountReq);
                AlbumImageList.Remove(ImageExistsCountReq);
                AlbumImageList.Remove(AllPSEImagesExistReq);
            }
            // All references to the current album have been removed. Now to re-insert
            // To do this, we need to cycle through all the images, and find the ones
            // that match the folder ID given, without
            OdbcCommand PSECommand = new OdbcCommand();
            PSECommand.CommandText = ImageTableSQLString;
            OdbcConnection PSEConnection = new OdbcConnection();
            PSEConnection.ConnectionString = @"Driver={Microsoft Access Driver (*.mdb)};DBQ=" + this.DBPath;
            PSEConnection.Open();
            PSECommand.Connection = PSEConnection;
            PSECommand.CommandType = CommandType.Text;
            OdbcDataReader ImageTableReader = PSECommand.ExecuteReader(CommandBehavior.CloseConnection);
            int ImagesInsertedCount = 0;
            int RowCount = 0;
            int ImagesExistsCount = 0;
            int ImagesNotExistsCount = 0;
            AlbumList = new NameValueCollection(G2int.GetAlbumList());
            String AlbumName = CheckGalleryAlbumFromCollectionId(FolderIdToInsert, G2int);
            //Get the images that already exist in gallery for this album
            NameValueCollection GalleryPhotos;
            try
            {
                GalleryPhotos = new NameValueCollection(G2int.GetPicturesForAlbum(AlbumName));
            }
            catch
            {
                Trace.WriteLine("Error while trying get pictures for album: " + AlbumName);
                GalleryPhotos = new NameValueCollection();
            }
            while (ImageTableReader.Read())
            {
                //Cycle through the image tags for this photo - check for stars, and if it is hidden
                Boolean HiddenPhoto = false;
                int StarsPhoto = 0; //Maybe I'll use this next version.
                Boolean TagMatchesPhoto = false;
                for (int i = 0; i < 100; i++)
                {
                    //20070831 >> SM - Implementing Stars
                    ulong CurrentFolderID = AllFolderInfoArray_Uints[RowCount, i];
                    if (HidenFolderID == CurrentFolderID)
                        HiddenPhoto = true;
                    if (FolderIdToInsert == CurrentFolderID)
                        TagMatchesPhoto = true;
                    if (FiveStarsFolderID != 0)
                    {
                        if (FiveStarsFolderID == CurrentFolderID)
                            StarsPhoto = 5;
                        else if (FourStarsFolderID == CurrentFolderID)
                            StarsPhoto = 4;
                        else if (ThreeStarsFolderID == CurrentFolderID)
                            StarsPhoto = 3;
                        else if (TwoStarsFolderID == CurrentFolderID)
                            StarsPhoto = 2;
                        else if (OneStarsFolderID == CurrentFolderID)
                            StarsPhoto = 1;
                    } //FiveStarsFolder != 0

                    //20070831 << SM - Implementing Stars
                }
                if (!HiddenPhoto & TagMatchesPhoto)
                {
                    // This image matches. Add it to AlbumImageList
                    ImagesInsertedCount++;
                    string ImageIDReq = ImageInfoReq + ImagesInsertedCount.ToString() + ".imageid";
                    string ImageFullPathReq = ImageInfoReq + ImagesInsertedCount.ToString() + ".fullpath";
                    string ImageFileNameReq = ImageInfoReq + ImagesInsertedCount.ToString() + ".filename";
                    string ImageShortCapReq = ImageInfoReq + ImagesInsertedCount.ToString() + ".shortcaption";
                    string ImageLongCapReq = ImageInfoReq + ImagesInsertedCount.ToString() + ".longcaption";
                    string ImageStarsReq = ImageInfoReq + ImagesInsertedCount.ToString() + ".stars";
                    string ImageExistsReq = ImageInfoReq + ImagesInsertedCount.ToString() + ".exists";

                    AlbumImageList.Set(ImageIDReq, ImageTableReader[0].ToString());
                    AlbumImageList.Set(ImageFullPathReq, RemoveLastCharacter(ImageTableReader[1].ToString()));
                    AlbumImageList.Set(ImageFileNameReq, RemoveLastCharacter(ImageTableReader[6].ToString()));
                    AlbumImageList.Set(ImageShortCapReq, RemoveLastCharacter(ImageTableReader[2].ToString()));
                    AlbumImageList.Set(ImageLongCapReq, RemoveLastCharacter(ImageTableReader[4].ToString()));
                    AlbumImageList.Set(ImageStarsReq, StarsPhoto.ToString());
                    //Determine if a current image.title matches the file name of anything we are about to upload
                    int UploadedImageCount = Convert.ToInt32(GalleryPhotos["image_count"]);
                    Boolean FileExists = false;
                    for (int i = 1; i <= UploadedImageCount; i++)
                    {
                        string UploadedFileName = GalleryPhotos["image.title." + i.ToString()];
                        UploadedFileName = UploadedFileName.Remove(UploadedFileName.LastIndexOf('.'));
                        String PSEImageId = ImageTableReader[0].ToString();
                        if (UploadedFileName == PSEImageId)
                        {
                            FileExists = true;
                            ImagesExistsCount++;
                        }
                    }
                    AlbumImageList.Set(ImageExistsReq, FileExists.ToString());
                    if (!FileExists)
                        ImagesNotExistsCount++;
                    Debug.WriteLine("Image Found: " + RemoveLastCharacter(ImageTableReader[1].ToString()));
                } // (!HiddenPhoto & TagMatchesPhoto)
                RowCount++;
            } // while (ImageTableReader.Read())
            AlbumImageList.Set(ImageCountReq, ImagesInsertedCount.ToString());
            AlbumImageList.Set(ImageExistsCountReq, ImagesExistsCount.ToString());
            Boolean AllPSEImagesExist = (ImagesNotExistsCount == 0);
            AlbumImageList.Set(AllPSEImagesExistReq, AllPSEImagesExist.ToString());

            return (0);
        }
        private void ConvertByteArrayToUintArray(Byte[] ByteArray, uint[] UintArray)
        {
            //Will take in an array of bytes, and convert it to an array of uints.
            //4 bytes = 1 uint.
            for (int i = 0; i < UintArray.Length; i++)
            {
                UintArray[i] = Convert.ToUInt32(ByteArray[i * 4] +
                                (ByteArray[(i * 4) + 1] * 256) +
                                (ByteArray[(i * 4) + 2] * 256 * 256) +
                                (ByteArray[(i * 4) + 3] * 256 * 256 * 256));
            }
        }
        private bool MatchUintArrays(uint[] UintArray1, uint[] UintArray2)
        {
            //function will compare the values of the two arrays given. If any of them
            //are the same, then return true, else return false
            for (int i = 0; i < UintArray1.Length; i++)
            {
                for (int j = 0; j < UintArray2.Length; j++)
                {
                    if (UintArray1[i] == UintArray2[j])
                    {
                        return (true);
                    }
                }
            }
            return (false);
        }
        public string ReturnAlbum(TreeView tvColl, Gallery2Interface G2int)
        {
            //Function will take in a treeview, which currently has the PSE collections in it
            //(with the one being uploaded from selected), and return the appropriate gallery album
            //to upload to. If necessary, it will create the album(s) to replicate the structure of PSE.
            TreeNode tnColl;
            tnColl = tvColl.SelectedNode;
            NameValueCollection nvColl;
            //Get the Gallery Album List
            //Debug.WriteLine("Trying to upload: " + tnColl.Text);
            nvColl = new NameValueCollection(G2int.GetAlbumList());
            Debug.WriteLine("album_count: " + nvColl["album_count"]);
            int albumCount = Convert.ToInt32(nvColl["album_count"]);
            for (int i = 1; i <= albumCount; i++)
            {
                string albumParentName = "album.parent." + i.ToString();
                string albumNameKey = "album.name." + i.ToString();
                string albumTitleKey = "album.title." + i.ToString();
                //Debug.WriteLine("Album No " + i.ToString() + " album.title: " + nvColl[albumTitleKey] +
                //    " album.name: " + nvColl[albumNameKey] +
                //    " album.parent: " + nvColl[albumParentName]);
            }
            return (CreateGalleryAlbum(tnColl, nvColl, G2int, false));
            //return(" "); //Get rid of this later
        }
        private string CreateGalleryAlbum(TreeNode tnCollPar, NameValueCollection nvColl, Gallery2Interface G2int, bool GalleryCreated)
        {
            //Function will retreive the matching gallery album for this PSE collection, or create it.
            bool ParentGalleryCreated = false;
            bool CreateAlbum = true;
            string ParentAlbumName = "";
            int albumCount;
            TreeNode tnCollLoc;
            //Get the parent of the current node
            tnCollLoc = tnCollPar.Parent;
            //If this is not the base level collection, then create the base level collection
            if (!tnCollPar.Level.Equals(0))
            {
                //Pass the parent back into this function
                ParentAlbumName = CreateGalleryAlbum(tnCollLoc, nvColl, G2int, ParentGalleryCreated);
            }
            else
            {
                //Find the top level gallery node, and keep going
                albumCount = Convert.ToInt32(nvColl["album_count"]);
                for (int i = 1; i <= albumCount; i++)
                {
                    string albumParentName = "album.parent." + i.ToString();
                    string albumNameKey = "album.name." + i.ToString();
                    string albumTitleKey = "album.title." + i.ToString();
                    if (nvColl[albumParentName] == "0")
                    {
                        ParentAlbumName = nvColl[albumNameKey];
                    }
                }
            }
            //Now determine the if this node exists
            //if AlbumNo is Null, then this must be the root PSE Collection. Therefore all we need to do
            //is find the root level Gallery album and return that. We know it exists - if it doesnt, something
            //is seriously wrong.
            albumCount = Convert.ToInt32(nvColl["album_count"]);
            for (int i = 1; i <= albumCount; i++)
            {
                string albumParentName = "album.parent." + i.ToString();
                string albumNameKey = "album.name." + i.ToString();
                string albumTitleKey = "album.title." + i.ToString();
                //Debug.WriteLine("Album No " + i.ToString() + " album.title: " + nvColl[albumTitleKey] +
                //    " album.name: " + nvColl[albumNameKey] +
                //    " album.parent: " + nvColl[albumParentName]);
                if ((nvColl[albumParentName] == ParentAlbumName) && (tnCollPar.Text == nvColl[albumTitleKey]))
                {
                    //This is the parent node. No need to do anything, just return the name (which is actually the id (number),
                    //not the word "Gallery"
                    GalleryCreated = false;
                    return (nvColl[albumNameKey]);
                }
            }
            //If we have gotten to here, then this is a child of something. We need to know if we need to create
            //a new Gallery album for this. (If the Parent Gallery was just created, we know we have to create all the children)
            CreateAlbum = ParentGalleryCreated;
            albumCount = Convert.ToInt32(nvColl["album_count"]);
            if (!ParentGalleryCreated)
            {
                for (int i = 1; i <= albumCount; i++)
                {
                    string albumParentName = "album.parent." + i.ToString();
                    string albumNameKey = "album.name." + i.ToString();
                    string albumTitleKey = "album.title." + i.ToString();
                    //Find all the children of the Parent
                    if (nvColl[albumParentName] == ParentAlbumName)
                    {
                        //Check if this this is the right child
                        if (tnCollPar.Text == nvColl[albumTitleKey])
                        {
                            //No need to create this album - it already exists.
                            CreateAlbum = false;
                            GalleryCreated = false;
                            return (nvColl[albumNameKey]);
                        }
                    }
                }
            }
            //If we have gotten to here, then we know that we need to create a gallery album
            //to match this PSE Collection.
            if (!G2int.CreateNewAlbum(tnCollPar.Text, "", ParentAlbumName))
            {
                //MessageBox.Show("New album " + addAlbumForm.textBoxNewAlbum.Text + " created!");
                //GetAndLoadAlbumsIntoTreeControl();
                MessageBox.Show("Error in creating album.");
            }
            //The new album has just been created, but we need to determine the name of it (the number that gallery
            //allocated to it) before exiting.
            NameValueCollection nvCollRefresh;
            //Get the Gallery Album List
            nvCollRefresh = new NameValueCollection(G2int.GetAlbumList());
            //Now to see if the if there is an album in nvCollRefresh which matches our criteria, and if it does,
            //return its "Name", else error (it really should be there).
            albumCount = Convert.ToInt32(nvCollRefresh["album_count"]);
            for (int i = 1; i <= albumCount; i++)
            {
                string albumParentName = "album.parent." + i.ToString();
                string albumNameKey = "album.name." + i.ToString();
                string albumTitleKey = "album.title." + i.ToString();
                if ((nvCollRefresh[albumParentName] == ParentAlbumName) && (nvCollRefresh[albumTitleKey] == tnCollPar.Text))
                {
                    return (nvCollRefresh[albumNameKey]);
                }
            }
            return (" ");
        }
        private string RemoveLastCharacter(string InputString)
        {
            //Simple function to remove the last character from the string, if the string is not zero length
            if (InputString.Length == 0)
            {
                return (InputString);
            }
            return (InputString.Remove(InputString.Length - 1));
        }
        public void SetCollectionTreeIcons(TreeView tvPSEColl)
        {
            //Function will take in a TreeView collection (The PSE Collections, as a treeview control.
            //It will assign a colour icon to each node, depending on its status. For bottom level nodes
            //(Nodes with no children), green means all photos have been uploaded, yellow means some have,
            //and red means none have. For non-bottom level nodes (those with children), if all its children
            //have a green icon, then so does it. If all of its children has a red icon, then so does it.
            //Else it has a yellow icon.
            Debug.WriteLine("NodeCount right at the start: " + tvPSEColl.Nodes.Count);
            int PSECollCount = tvPSEColl.Nodes.Count;
            if (PSECollCount == 0)
                return;
            AlbumList = new NameValueCollection(G2int.GetAlbumList());
            for (int i = 0; i < PSECollCount; i++)
            {
                TreeNode tnPSECollNode = tvPSEColl.Nodes[i];
                if (tnPSECollNode.Level == 0)
                {
                    //Debug.WriteLine("Processing Node top level node: " + tnPSECollNode.Text);
                    int IconColour = SetCollectionNodeIcon(tnPSECollNode, tvPSEColl, G2int);
                }
            }

        }
        private int SetCollectionNodeIcon(TreeNode tnPSEColl, TreeView tvPSEColl, Gallery2Interface G2int)
        {
            Debug.WriteLine("Processing node: " + tnPSEColl.Text);
            //Function will set the colour of this nodes icon.
            //0 = White, 1 = Red, 2 = Yellow, 3 = Green
            int IconColour = 0; //Starts off as white.

            //Firstly, process any children nodes of this
            int NodeCount = tnPSEColl.Nodes.Count;
            Boolean NodeHasChildren = false;
            for (int i = 0; i < NodeCount; i++)
            {
                TreeNode tnChildPSEColl = tnPSEColl.Nodes[i];

                if (tnChildPSEColl.Parent != null)
                {
                    if (tnChildPSEColl.Parent.Name == tnPSEColl.Name)
                    {
                        NodeHasChildren = true;
                        //Current node is a child of tnColl. We need to process this.
                        Debug.WriteLine("Calling self. i = " + i.ToString());
                        int ReturnIconColour = SetCollectionNodeIcon(tnChildPSEColl, tvPSEColl, G2int);
                        if (IconColour != 2) //If the IconColour is yellow, then we leave it at yellow
                        {
                            switch (ReturnIconColour)
                            {
                                case 1: // Red
                                    if (IconColour > 1) //if IconColour is currently green or Yellow
                                        IconColour = 2; //Set to Yellow
                                    else
                                        IconColour = 1; //Set to red
                                    break;
                                case 2: // Yellow
                                    IconColour = 2; //Set to Yellow
                                    break;
                                case 3: // Green
                                    if ((IconColour == 1) | (IconColour == 2)) // If IconColour is currnetly red or Yellow
                                        IconColour = 2; // Set to Yellow
                                    else
                                        IconColour = 3; // Set to Green
                                    break;
                            }
                            //if (ReturnIconColour == 2)
                            //{

                            //}
                        }
                    }
                }
            }
            //}
            //Now to process the photos of this collection, but only if there are no child nodes (as
            //PSE does not allow a collection with photos to contain other collections)
            if (!NodeHasChildren)
            {
                //At this point, AlbumList should already have a list of all the albums
                //string Album = ReturnAlbum(tvColl, G2int);
                String AlbumName = CheckGalleryAlbum(tnPSEColl, G2int);
                //We have the AlbumName. Now to see if the pictures match up between them.
                //Get the Gallery Album List
                //Debug.WriteLine("Trying to upload: " + tnColl.Text);
                NameValueCollection GalleryPhotos;
                try
                {
                    GalleryPhotos = new NameValueCollection(G2int.GetPicturesForAlbum(AlbumName));
                }
                catch
                {
                    Trace.WriteLine("Error while trying get pictures for album: " + AlbumName);
                    GalleryPhotos = new NameValueCollection();
                }
                Debug.WriteLine("Photo Count for node " + tnPSEColl.Text + " " + GalleryPhotos.Count.ToString());
                Debug.WriteLine("Photo Keys Count for node " + tnPSEColl.Text + " " + GalleryPhotos.Keys.Count.ToString());
                //string ImageInfoReq = "folderid." + tnPSEColl.Name.ToString() + ".image.";
                string ImageCountReq = "folderid." + tnPSEColl.Name.ToString() + ".imagecount";
                string ImageExistsCountReq = "folderid." + tnPSEColl.Name.ToString() + ".imageexistcount";
                string AllPSEImagesExistReq = "folderid." + tnPSEColl.Name.ToString() + ".allpseimagesexist";

                int CollectionPhotoCount = Convert.ToInt32(AlbumImageList[ImageCountReq]);
                int CollectionExistsCount = Convert.ToInt32(AlbumImageList[ImageExistsCountReq]);
                string blahblah = AlbumImageList[AllPSEImagesExistReq];
                Boolean AllPSEImagesExist = Convert.ToBoolean(AlbumImageList[AllPSEImagesExistReq]);
                Debug.WriteLine("Getting stufffor name: " + tnPSEColl.Name.ToString() + "CollectionPhotoCount is: " +
                    CollectionPhotoCount.ToString() + " CollectionExistsCount is: " + CollectionExistsCount.ToString());
                if (CollectionExistsCount == 0)
                    IconColour = 1; //Red
                else if (!AllPSEImagesExist)
                    IconColour = 2; //Yellow
                else
                    IconColour = 3; //Green


                /*
                //For testing purposes only
                //int ImageCount = Convert.ToInt32(GalleryPhotos["image_count"]);
                //for (int i = 1; i <= ImageCount; i++)
                //{
                    string imageTitle = "image.title." + i.ToString();
                    string imageCaption = "image.caption." + i.ToString();
                    string imageName = "image.name." + i.ToString();
                    Debug.WriteLine("Image" + i.ToString() + " image.title: " + GalleryPhotos[imageTitle] +
                        " image.caption: " + GalleryPhotos[imageCaption] +
                        " album.name: " + GalleryPhotos[imageName]);
                }
                */
            }
            tnPSEColl.ImageIndex = IconColour;
            tnPSEColl.SelectedImageIndex = tnPSEColl.ImageIndex;
            return (IconColour);
        }
        private string CheckGalleryAlbum(TreeNode tnCollPar, Gallery2Interface G2int)
        {
            //Function will retreive the matching gallery album for this PSE collection if it exists
            bool ParentGalleryCreated = false; //Still here as I copied this function from above
            bool CreateAlbum = true; //Still here as I copied this function from above
            string ParentAlbumName = "";
            int albumCount;
            TreeNode tnCollLoc;
            //Get the parent of the current node
            tnCollLoc = tnCollPar.Parent;
            //If this is not the base level collection, then check the base level collections
            if (!tnCollPar.Level.Equals(0))
            {
                //Pass the parent back into this function
                ParentAlbumName = CheckGalleryAlbum(tnCollLoc, G2int);
                if (ParentAlbumName == "")
                    return ("");
            }
            else
            {
                //Find the top level gallery node, and keep going
                albumCount = Convert.ToInt32(AlbumList["album_count"]);
                for (int i = 1; i <= albumCount; i++)
                {
                    string albumParentName = "album.parent." + i.ToString();
                    string albumNameKey = "album.name." + i.ToString();
                    string albumTitleKey = "album.title." + i.ToString();
                    if (AlbumList[albumParentName] == "0")
                    {
                        ParentAlbumName = AlbumList[albumNameKey];
                    }
                }
            }
            //Now determine the if this node exists
            //if AlbumNo is Null, then this must be the root PSE Collection. Therefore all we need to do
            //is find the root level Gallery album and return that. We know it exists - if it doesnt, something
            //is seriously wrong.
            albumCount = Convert.ToInt32(AlbumList["album_count"]);
            for (int i = 1; i <= albumCount; i++)
            {
                string albumParentName = "album.parent." + i.ToString();
                string albumNameKey = "album.name." + i.ToString();
                string albumTitleKey = "album.title." + i.ToString();
                //Debug.WriteLine("Album No " + i.ToString() + " album.title: " + nvColl[albumTitleKey] +
                //    " album.name: " + nvColl[albumNameKey] +
                //    " album.parent: " + nvColl[albumParentName]);
                if ((AlbumList[albumParentName] == ParentAlbumName) && (tnCollPar.Text == AlbumList[albumTitleKey]))
                {
                    //This is the parent node. No need to do anything, just return the name (which is actually the id (number),
                    //not the word "Gallery"
                    return (AlbumList[albumNameKey]);
                }
            }
            //If we have gotten to here, then this is a child of something. We need to know if we need to create
            //a new Gallery album for this. (If the Parent Gallery was just created, we know we have to create all the children)
            CreateAlbum = ParentGalleryCreated;
            albumCount = Convert.ToInt32(AlbumList["album_count"]);
            if (!ParentGalleryCreated)
            {
                for (int i = 1; i <= albumCount; i++)
                {
                    string albumParentName = "album.parent." + i.ToString();
                    string albumNameKey = "album.name." + i.ToString();
                    string albumTitleKey = "album.title." + i.ToString();
                    //Find all the children of the Parent
                    if (AlbumList[albumParentName] == ParentAlbumName)
                    {
                        //Check if this this is the right child
                        if (tnCollPar.Text == AlbumList[albumTitleKey])
                        {
                            //No need to create this album - it already exists.
                            CreateAlbum = false;
                            return (AlbumList[albumNameKey]);
                        }
                    }
                }
            }
            //If we get to here, then we know the gallery does not exist
            return ("");
        }
        private string CheckGalleryAlbumFromCollectionId(uint CollectionId, Gallery2Interface G2int)
        {
            if (CollectionId == 0)
                return ("");
            //Function will retreive the matching gallery album for this PSE collection if it exists
            //Had to re-write this function to work from an integer
            bool ParentGalleryCreated = false; //Still here as I copied this function from above
            bool CreateAlbum = true; //Still here as I copied this function from above
            string ParentAlbumName = "";
            int albumCount;
            OleDbDataAdapter daFolderTableChild =
                new OleDbDataAdapter("Select * From FolderTable WHERE fFolderID = " + CollectionId.ToString(), PSEConnection);
            DataTable dtFolderTableChild = new DataTable();
            daFolderTableChild.Fill(dtFolderTableChild);
            uint ParentFolderId = Convert.ToUInt32(dtFolderTableChild.Rows[0]["fParentFolderId"]);
            //If this is not the base level collection, then keep going up the collection levels
            if ((ParentFolderId != 0) & (ParentFolderId != CollTopLevelFolderID))
            {
                ParentAlbumName = CheckGalleryAlbumFromCollectionId(ParentFolderId, G2int);
                if (ParentAlbumName == "")
                    return ("");
            }
            else
            {
                //Find the top level node
                albumCount = Convert.ToInt32(AlbumList["album_count"]);
                for (int i = 1; i <= albumCount; i++)
                {
                    string albumParentName = "album.parent." + i.ToString();
                    string albumNameKey = "album.name." + i.ToString();
                    string albumTitleKey = "album.title." + i.ToString();
                    if (AlbumList[albumParentName] == "0")
                    {
                        ParentAlbumName = AlbumList[albumNameKey];
                    }
                }
            }


            //Now determine the if this node exists
            //if AlbumNo is Null, then this must be the root PSE Collection. Therefore all we need to do
            //is find the root level Gallery album and return that. We know it exists - if it doesnt, something
            //is seriously wrong.
            albumCount = Convert.ToInt32(AlbumList["album_count"]);
            for (int i = 1; i <= albumCount; i++)
            {
                string albumParentName = "album.parent." + i.ToString();
                string albumNameKey = "album.name." + i.ToString();
                string albumTitleKey = "album.title." + i.ToString();
                //Debug.WriteLine("Album No " + i.ToString() + " album.title: " + nvColl[albumTitleKey] +
                //    " album.name: " + nvColl[albumNameKey] +
                //    " album.parent: " + nvColl[albumParentName]);
                if ((AlbumList[albumParentName] == ParentAlbumName) &&
                    (dtFolderTableChild.Rows[0]["fFolderName"].ToString() == AlbumList[albumTitleKey]))
                {
                    //This is the parent node. No need to do anything, just return the name (which is actually the id (number),
                    //not the word "Gallery"
                    return (AlbumList[albumNameKey]);
                }
            }
            //If we have gotten to here, then this is a child of something. We need to know if we need to create
            //a new Gallery album for this. (If the Parent Gallery was just created, we know we have to create all the children)
            CreateAlbum = ParentGalleryCreated;
            albumCount = Convert.ToInt32(AlbumList["album_count"]);
            if (!ParentGalleryCreated)
            {
                for (int i = 1; i <= albumCount; i++)
                {
                    string albumParentName = "album.parent." + i.ToString();
                    string albumNameKey = "album.name." + i.ToString();
                    string albumTitleKey = "album.title." + i.ToString();
                    //Find all the children of the Parent
                    if (AlbumList[albumParentName] == ParentAlbumName)
                    {
                        //Check if this this is the right child
                        if (dtFolderTableChild.Rows[0]["fFolderName"].ToString() == AlbumList[albumTitleKey])
                        {
                            //No need to create this album - it already exists.
                            CreateAlbum = false;
                            return (AlbumList[albumNameKey]);
                        }
                    }
                }
            }
            //If we get to here, then we know the gallery does not exist
            return ("");
        }
        public void UpdateIconsAfterUpload(uint[] CollectionIdArray, TreeView tvPSEColl)
        {
            // Will update the icons for all of the collections in CollectionIdArray

            // Update the AlbumImageList
            PopulateAlbumImageList(CollectionFolderIDArray);
            //Update the treeview icons
            this.SetCollectionTreeIcons(tvPSEColl);
        }
        public string ReturnTagsForPicture(uint pictureID, bool includePersonTags, bool includePlacesTags, bool includeEventsTags, bool includeOtherTags)
        {
            // function will return all ofthe people,place,event and other tags for a given photo, based on the
            // critieria provided.
            // We can assume we are already connected to the database
            string ReturnTags = "";
            OdbcCommand PSECommand = new OdbcCommand();
            //PSECommand.CommandText = "SELECT fImageId, fMediaFullPath, fImageOriginalFileName, fFolderInfoArray from ImageTable";
            PSECommand.CommandText = "SELECT ImageTable.fImageId, ImageTable.fMediaFullPath, " +
                "MediaShortCaptionTable.fMediaShortCaption, ImageTable.fFolderInfoArray, " +
                "ImageLongCaptionTable.fImageLongCaption, ImageTable.fImageTime, ImageTable.fImageOriginalFileName " +
                "FROM (ImageTable LEFT JOIN MediaShortCaptionTable ON " +
                "ImageTable.fMediaShortCaptionIdFromMedia = MediaShortCaptionTable.fMediaShortCaptionId) LEFT JOIN " +
                "ImageLongCaptionTable ON ImageTable.fImageLongCaptionIdFromImage = ImageLongCaptionTable.fImageLongCaptionId" +
                " WHERE ImageTable.fImageId = " + pictureID.ToString();
            OdbcConnection PSEodbcConnection = new OdbcConnection();
            //PSEConnection.ConnectionString = @"Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\Users\shanon\Pictures\Adobe Photoshop Album\Shanons.psa";
            //LocConn.Driver = @"Provider=Microsoft.Jet.OLEDB.4.0";
            //LocConn.ConnectionString = @"C:\Users\shanon\Pictures\Adobe Photoshop Album\Shanons.psa";
            PSEodbcConnection.ConnectionString = @"Driver={Microsoft Access Driver (*.mdb)};DBQ=" + this.DBPath;

            PSEodbcConnection.Open();
            PSECommand.Connection = PSEodbcConnection;
            PSECommand.CommandType = CommandType.Text;
            OdbcDataReader imageReader = PSECommand.ExecuteReader(CommandBehavior.CloseConnection);
            byte[] FolderInfoArray_Bytes;
            uint[] FolderInfoArray_Uints;
            FolderInfoArray_Bytes = new byte[400];
            FolderInfoArray_Uints = new uint[100];
            while (imageReader.Read())
            {
                //This is where things get tricky. The following bits of code will:
                //a) Grab the fFolderInfoArray field (a binary field) and put it into FolderInfoArray_Bytes,
                //   which is a 400 member array of Bytes
                //b) Convert these 400 bytes into 100 uints, and populate the FolderInfoArray_Uints (a 100
                //   member array of uints).

                //Firstly we clear the two arrays.
                Array.Clear(FolderInfoArray_Bytes, 0, FolderInfoArray_Bytes.Length);
                Array.Clear(FolderInfoArray_Uints, 0, FolderInfoArray_Uints.Length);

                //Populate the FolderInfoArray_Bytes array
                imageReader.GetBytes(3, 0, FolderInfoArray_Bytes, 0, FolderInfoArray_Bytes.Length);
                //Populatethe FolderInfoArray_Uints array
                this.ConvertByteArrayToUintArray(FolderInfoArray_Bytes, FolderInfoArray_Uints);
                //Now we should have the FolderInfoArray_Uints array full of the folders linked to this record.
                //We need to go through these and find any that are of the kind we want to return
                for (int i = 0; i < FolderInfoArray_Uints.Length; i++)
                {
                    if (FolderInfoArray_Uints[i] != 0)
                    {
                        OleDbDataAdapter daFolderTable;
                        daFolderTable =
                            new OleDbDataAdapter("Select * From FolderTable WHERE fFolderiD = " + FolderInfoArray_Uints[i].ToString(), PSEConnection);
                        DataTable dtFolderTable = new DataTable();
                        daFolderTable.Fill(dtFolderTable);
                        ulong fFolderAttributes = Convert.ToUInt64(dtFolderTable.Rows[0]["fFolderAttributes"].ToString());
                        switch (fFolderAttributes)
                        {
                            case PersonFolderAtt:
                                if (includePersonTags == true)
                                    ReturnTags = AddTagToTagString(ReturnTags, dtFolderTable.Rows[0]["fFolderName"].ToString());
                                break;
                            case PlaceFolderAtt:
                                if (includePlacesTags == true)
                                    ReturnTags = AddTagToTagString(ReturnTags, dtFolderTable.Rows[0]["fFolderName"].ToString());
                                break;
                            case EventFolderAtt:
                                if (includeEventsTags == true)
                                    ReturnTags = AddTagToTagString(ReturnTags, dtFolderTable.Rows[0]["fFolderName"].ToString());
                                break;
                            case OtherFolderAtt:
                                if (includeOtherTags == true)
                                    ReturnTags = AddTagToTagString(ReturnTags, dtFolderTable.Rows[0]["fFolderName"].ToString());
                                break;
                        }
                        //CollTopLevelFolderID = Convert.ToUInt64(dt_TopLevelColl.Rows[0]["fFolderID"].ToString());
                    }
                }
            }
            return ReturnTags;
        } //ReturnTagsForPicture
        string AddTagToTagString(string TagString, string TagToAdd)
        {
            if (TagString.ToString() == "")
                TagString = TagToAdd.ToString();
            else
                TagString = TagString.ToString() + ", " + TagToAdd.ToString();
            return TagString;

        }
    }
}
